import { isArray, isBoolean, isFunction, isObject, noop } from 'lodash-es'
import { cloneDeep } from 'lodash-es'
import { fieldsMap, pageSize, tableColumnProps } from '@lib/default'
import { resolveDicts } from '../../utils'
import { getAndRemoveValue, toKebabCase } from '../../../utils'
import { useTableSettingRecord } from './tableSettingRecord'

/**
 * 处理表格组件的config
 *
 * @param {*} config
 */
export function normalizeConfig(config) {
  const conf = cloneDeep(config)

  conf.columns = resolveTableColumns(conf)

  const request = conf.requestApi
  const requestApi = conf.requestApi = {}
  if (isFunction(request)) {
    requestApi.handler = request
  } else if (isObject(request)) {
    requestApi.handler = request.handler
  }
  requestApi.pageSize = request.pageSize || pageSize
  requestApi.onSuccess = request.onSuccess || noop
  requestApi.onError = request.onError || noop
  requestApi.onComplete = request.onComplete || noop

  // 默认表格一加载就去获取数据
  conf.immediate = isBoolean(conf.immediate) ? conf.immediate : true

  // 字段映射
  conf.fieldsMap = Object.assign({}, fieldsMap, conf.fieldsMap)

  // 监听事件的驼峰式命名转为短横线命名
  const listeners = conf.listeners || (conf.listeners = {})
  let handler
  Object.keys(listeners).forEach(methodName => {
    handler = getAndRemoveValue(listeners, methodName)
    listeners[toKebabCase(methodName)] = handler
  })

  return conf
}

/**
 * 处理表格列
 */
function resolveTableColumns(conf) {
  const columns = conf.columns || (conf.columns = [])
  const result = []
  let column, width

  const { widthRecord, isShowRecord, sortRecord } = useTableSettingRecord(conf.name)

  let  prop
  for (let index = 0, len = columns.length; index < len; index++) {
    column = columns[index]
    prop = getAndRemoveValue(column, 'prop') || ''

    column.options = Object.assign({}, tableColumnProps, {
      prop,
      label: getAndRemoveValue(column, 'label') || '',
      width: getAndRemoveValue(column, 'width')
    }, column.options)

    if ((width = widthRecord[prop])) {
      column.options.width = width
    }

    column.show = isBoolean(isShowRecord[prop])
      ? isShowRecord[prop]
      : true

    defineDictsRender(column)

    result.push(column)
  }

  return sortColumnsByRecord(result, sortRecord)
}

/**
 * 对表格列进行排序
 */
function sortColumnsByRecord(columns, record) {
  const result = []

  // 循环把表格列放到对应位置
  // 对于不存在缓存记录中的列，则可能是后面新增的表格字段，
  // 将其存放在tasks列表中，待循环结束再一一插进去
  const tasks = []
  let position, col, prevCol
  for (let i = 0, len = columns.length; i < len; i++) {
    col = columns[i]
    position = record[col.options.prop]
    if (position !== undefined) {
      result[position] = col
    } else {
      tasks.push({
        prevCol,
        col
      })
    }
    prevCol = col
  }

  // 根据原来的位置插入其他表格列
  tasks.forEach(insert => {
    const prevIndex = result.indexOf(insert.prevCol)
    result.splice(prevIndex + 1, 0, insert.col)
  })

  return result.filter(Boolean)
}

/**
 * 当有配置了字典数据时，重定义一下render
 */
async function defineDictsRender(column) {
  const dicts = resolveDicts(column)
  if (isArray(dicts)) {
    const render = column.render
    column.render = function(h, attrs) {
      let data = column.dicts.find(d => d.value === attrs.value)
      if (data) {
        data = { value: data.label, color: data.color }
      } else {
        data = { value: attrs.value }
      }
      if (render) {
        return render(h, Object.assign({}, attrs, data))
      } else {
        return h(
          'span',
          data.color ? { style: `color:${data.color}` } : {},
          data.value
        )
      }
    }
  }
}
